#include <QFileDialog>
#include <QMessageBox>
#include "decoderwidget.h"
#include "ui_decoderwidget.h"

#define CODE_SCAN_TIME 200  //扫描时间间隔
#define BEEP_TIME 1500  //提示音播报时间间隔
DecoderWidget::DecoderWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DecoderWidget),
    m_pCamera1(NULL),
    m_pCamera2(NULL),
    m_pImageCapture1(NULL),
    m_pImageCapture2(NULL),
    videoOpen1(0),
    videoOpen2(0)
{
    ui->setupUi(this);

    //初始化UI界面
    initUI();
    //读取二维码定时器
    videoTime = new QTimer(this);
    connect(videoTime,SIGNAL(timeout()),this,SLOT(on_videoTime()));
    //videoTime->start(100);

    //二维码解码器
    decode = new QZXing(QZXing::DecoderFormat_MAXICODE);
    decode->setDecoder(QZXing::DecoderFormat_QR_CODE);// | QZXing::DecoderFormat_CODE_128);
    addTableData("20B02012172;20211102;W288;","20B02012172;20211102;W288;");
    addTableData("20B02012173;20211102;W288;","20B02012173;20211102;W288;");
    addTableData("20B02012174;20211102;W288;","20B02012174;20211102;W288;");
    addTableData("20B02012175;20211102;W288;","20B02012175;20211102;W288;");
    addTableData("20B02012176;20211102;W288;","20B02012179;20211102;W288;");
    addTableData("20B02012177;20211102;W288;","20B02012177;20211102;W288;");
    addTableData("20B02012178;20211102;W288;","20B02012178;20211102;W288;");
    for(int i = 0;i < 1320;i ++)
        addTableData("20B0201217x;20211102;W288;","20B0201217x;20211102;W288;");

}

DecoderWidget::~DecoderWidget()
{
    delete ui;
}

void DecoderWidget::initUI()
{
    //初始化表格样式
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);  //设置表格内容不可编辑
    ui->tableWidget->verticalHeader()->setHidden(true);       //隐藏行号列
    ui->tableWidget->setShowGrid(false);
    ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);  //设置滚动隐藏
    //ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);		//设置不可选
    ui->tableWidget->setSelectionBehavior ( QAbstractItemView::SelectRows); //设置选择行为，以行为单位
    //ui->tableWidget->setSelectionMode ( QAbstractItemView::SingleSelection); //设置选择模式，只能选择单行
    ui->tableWidget->setColumnWidth(0,40);
    ui->tableWidget->setColumnWidth(3,80);
    ui->tableWidget->setColumnWidth(1,165);
    ui->tableWidget->setColumnWidth(2,165);
    //ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    //初始化标签样式
    ui->label_code1->setAutoFillBackground(true);
    ui->label_code2->setAutoFillBackground(true);
    ui->label_check->setAutoFillBackground(true);
    setLabStatus(ui->label_code1,"通道一摄像头未打开",QColor(180,180,180));
    setLabStatus(ui->label_code2,"通道二摄像头未打开",QColor(180,180,180));
    //初始化表格样式
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);  //设置表格内容不可编辑
    ui->tableWidget->verticalHeader()->setHidden(true);         //隐藏行号列
    ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);  //设置滚动隐藏
    //ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);		//设置不可选

    ui->tableWidget->setColumnWidth(0,40);
    ui->tableWidget->setColumnWidth(3,80);
    ui->tableWidget->setColumnWidth(1,200);
    ui->tableWidget->setColumnWidth(2,200);
    //ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    //初始化标签样式
    ui->label_code1->setAutoFillBackground(true);
    ui->label_code2->setAutoFillBackground(true);
    ui->label_check->setAutoFillBackground(true);
    setLabStatus(ui->label_code1,"通道一摄像头未打开",QColor(180,180,180));
    setLabStatus(ui->label_code2,"通道二摄像头未打开",QColor(180,180,180));

    //若连接到多个摄像头设备，获取可使用的摄像头信息
    CameraInfoList = QCameraInfo::availableCameras();
    for(int i = 0;i < CameraInfoList.size();i ++)
    {
        ui->comboBox->addItem(CameraInfoList.at(i).description());
        ui->comboBox_2->addItem(CameraInfoList.at(i).description());
    }
}
void DecoderWidget::on_btnInput_clicked()
{
    if(m_pCamera1 == NULL && m_pImageCapture1 == NULL)
    {
        m_pCamera1 = new QCamera(CameraInfoList.at(ui->comboBox->currentIndex()));
        m_pImageCapture1 = new QCameraImageCapture(m_pCamera1);
        m_pCamera1->setCaptureMode(QCamera::CaptureStillImage);  //将其采集为图片
        m_pCamera1->setViewfinder(ui->videoWidget);    //设置取景器
        m_pImageCapture1->setCaptureDestination(QCameraImageCapture::CaptureToFile);     //设置采集目标
        connect(m_pImageCapture1, SIGNAL(imageCaptured(int,QImage)), this, SLOT(cameraImageCaptured(int,QImage)));   //读取图片
        m_pCamera1->start();    //开启相机
        videoOpen1 = 1;
        ui->btnInput->setText("关闭");
        setLabStatus(ui->label_code1,"未启动扫描",QColor(180,180,180));
    }
    else
    {
        m_pCamera1->stop();
        videoOpen1 = 0;
        setLabStatus(ui->label_code1,"通道一摄像头已关闭",QColor(180,180,180));
        delete m_pCamera1;
        delete m_pImageCapture1;
        m_pCamera1 = NULL;
        m_pImageCapture1 = NULL;
        ui->btnInput->setText("打开");

        if(videoTime->isActive())   //有任意摄像头关闭则停止扫描
            videoTime->stop();
        ui->pushButton->setText("启动识别");
        setLabStatus(ui->label_check,"识别已停止",QColor(180,180,180));
    }
}

void DecoderWidget::on_btnInput_2_clicked()
{
    if(m_pCamera2 == NULL && m_pImageCapture2 == NULL)
    {
        m_pCamera2 = new QCamera(CameraInfoList.at(ui->comboBox_2->currentIndex()));
        m_pImageCapture2 = new QCameraImageCapture(m_pCamera2);
        m_pCamera2->setCaptureMode(QCamera::CaptureStillImage);
        m_pCamera2->setViewfinder(ui->videoWidget2);
        m_pImageCapture2->setCaptureDestination(QCameraImageCapture::CaptureToFile);
        connect(m_pImageCapture2, SIGNAL(imageCaptured(int,QImage)), this, SLOT(cameraImageCaptured2(int,QImage)));
        m_pCamera2->start();
        videoOpen2 = 1;
        ui->btnInput_2->setText("关闭");
        setLabStatus(ui->label_code2,"未启动扫描",QColor(180,180,180));
    }
    else
    {
        m_pCamera2->stop();
        videoOpen2 = 0;
        setLabStatus(ui->label_code2,"通道二摄像头已关闭",QColor(180,180,180));
        delete m_pCamera2;
        delete m_pImageCapture2;
        m_pCamera2 = NULL;
        m_pImageCapture2 = NULL;
        ui->btnInput_2->setText("打开");
        if(videoTime->isActive())
            videoTime->stop();
        ui->pushButton->setText("启动识别");
        setLabStatus(ui->label_check,"识别已停止",QColor(180,180,180));
    }
}

void DecoderWidget::on_pushButton_clicked()
{
    if(videoTime == NULL) return;
    if(videoTime->isActive())
    {
        videoTime->stop();
        ui->pushButton->setText("启动识别");
        setLabStatus(ui->label_check,"识别已停止",QColor(180,180,180));
    }
    else
    {
        if(videoOpen1 && videoOpen2)
        {
            videoTime->start(CODE_SCAN_TIME);
            ui->pushButton->setText("停止识别");
        }
        else
        {
            showHintLabel(this,"确保双通道摄像头都打开");
        }
    }
}

void DecoderWidget::on_pushButton_2_clicked()       //清空表格
{
    for(int i = ui->tableWidget->rowCount()-1;i >=0 ;i --)
        ui->tableWidget->removeRow(i);
}

void DecoderWidget::on_videoTime()
{
    if(videoOpen1 && m_pImageCapture1 != NULL)
        m_pImageCapture1->capture();    //发送获取一帧数据的信号

    if(videoOpen2 && m_pImageCapture2 != NULL)
        m_pImageCapture2->capture();
}

void DecoderWidget::cameraImageCaptured(int i, QImage img)  //100ms一次收到二维码
{
    code1 = decode->decodeImage(img).trimmed();     //解析得到二维码信息

    if(!code1.isEmpty())
    {
        setLabStatus(ui->label_code1,code1,QColor(150,255,150));
        QStringList labList = code1.split(";"); //解析二维码内容

        if(labList.size() >= 3)
        {
            ui->label_ref->setText(labList.at(2));
            ui->label_lot->setText(labList.at(0));
            ui->label_time->setText(labList.at(1));
        }
    }
    else
    {
        ui->label_ref->setText("-");
        ui->label_lot->setText("-");
        ui->label_time->setText("-");
        setLabStatus(ui->label_code1,"扫描中...",QColor(180,180,180));
    }
    resultCheckUpdata();        //更新结果判断
}

void DecoderWidget::cameraImageCaptured2(int i, QImage img) //100ms一次收到二维码
{
    code2 = decode->decodeImage(img).trimmed();
    if(!code2.isEmpty())
    {
        setLabStatus(ui->label_code2,code2,QColor(150,255,150));
        QStringList labList = code2.split(";");
        if(labList.size() >= 3)
        {
            ui->label_ref_2->setText(labList.at(2));
            ui->label_lot_2->setText(labList.at(0));
            ui->label_time_2->setText(labList.at(1));
        }
    }
    else
    {
        ui->label_ref_2->setText("-");
        ui->label_lot_2->setText("-");
        ui->label_time_2->setText("-");
        setLabStatus(ui->label_code2,"扫描中...",QColor(180,180,180));
    }
    resultCheckUpdata();
}

void DecoderWidget::resultCheckUpdata()
{
    if(code1.isEmpty() || code2.isEmpty())      //至少有一个未识别到
    {
        setLabStatus(ui->label_check,"扫描中",QColor(180,180,180));//显示扫描中
    }
    else    //两个都识别到
    {
        QString strBuff = code1 + " | " + code2 + " | ";
        if(code1 == code2)      //判断两边二维码是否相等
        {
            static QString lastCode;
            strBuff += "1";
            setLabStatus(ui->label_check,"匹配通过",QColor(0,200,0));
            if(lastCode != code1)
            {
                QApplication::beep();
                QTimer::singleShot(BEEP_TIME,this,[=](){
                    lastCode.clear();
                });
            }
            lastCode = code1;
        }
        else
        {
            strBuff += "0";
            setLabStatus(ui->label_check,"匹配失败",QColor(255,30,30));
        }
        if(!codeList.contains(strBuff))
        {
            codeList.append(strBuff);
            qDebug()<<"code List :"<<codeList;

            addTableData(code1,code2);
        }
    }
}

void DecoderWidget::setLabStatus(QLabel *lab,QString text,QColor color)
{
    lab->clear();
    lab->setText(text);
    QPalette palette;
    palette.setColor(QPalette::Background, color);
    lab->setPalette(palette);
}

#include <QDesktopWidget>
void DecoderWidget::showHintLabel(QWidget *parentWin, QString strText, QString strFontSize, QString strColor, QString strBgColor)
{
    if(nullptr == parentWin)
        parentWin = QApplication::desktop()->screen();

    QFrame *pFrame = new QFrame();  //为了兼容parent为nullptr时的圆角边框  方法是背景透明 上边叠加圆角控件
    pFrame->setWindowFlags(Qt::FramelessWindowHint);    //去除外框
    pFrame->setAttribute(Qt::WA_TranslucentBackground); //设置窗体背景透明

    QLabel *pLabel = new QLabel(pFrame);    //创建显示标签
    pLabel->setAlignment(Qt::AlignCenter);  //文字居中显示
    pLabel->setStyleSheet(QString("QLabel{background:%1;color:%2;font:%3 SimHei;border-radius:5px;}")
                              .arg(strBgColor).arg(strColor).arg(strFontSize)); //社长标签风格
    pLabel->setText(strText);                   //设置文字内容
    pLabel->adjustSize();
    pLabel->resize(pLabel->size() + QSize(120,120));
    //设置pFrame大小和位置
    pFrame->resize(pLabel->size()); //设置大小为label大小
    pFrame->move((parentWin->width()-pFrame->width())/2   + parentWin->pos().x(),
                 (parentWin->height()-pFrame->height())/2 + parentWin->pos().y());
    pFrame->show();

    //创建动画，使窗口淡化消失
    QPropertyAnimation *pAnimation = new QPropertyAnimation(pFrame,"windowOpacity",this);
    pAnimation->setDuration(2000);
    pAnimation->setEasingCurve(QEasingCurve::InCirc);
    pAnimation->setStartValue(1.0);
    pAnimation->setEndValue(0.0);
    pAnimation->start();        //启动动画
    //动画结束后删除创建的资源
    connect(pAnimation,&QPropertyAnimation::finished,[=]{
        delete pAnimation;
        delete pFrame;
    });
}

void DecoderWidget::addTableData(QString code1,QString code2)
{
    ui->tableWidget->setRowCount(ui->tableWidget->rowCount()+1);
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 0, new QTableWidgetItem(QString::number(ui->tableWidget->rowCount())));
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 1, new QTableWidgetItem(code1));
    ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 2, new QTableWidgetItem(code2));
    if(code1 == code2)
    {
        ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 3, new QTableWidgetItem("通过"));
        ui->tableWidget->item(ui->tableWidget->rowCount()-1,3)->setBackgroundColor(QColor(120,255,120));
    }
    else
    {
        ui->tableWidget->setItem(ui->tableWidget->rowCount()-1, 3, new QTableWidgetItem("缺陷"));
        ui->tableWidget->item(ui->tableWidget->rowCount()-1,3)->setBackgroundColor(QColor(255,120,120));
    }

    ui->tableWidget->item(ui->tableWidget->rowCount()-1,0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    ui->tableWidget->item(ui->tableWidget->rowCount()-1,1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    ui->tableWidget->item(ui->tableWidget->rowCount()-1,2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    //ui->tableWidget->item(ui->tableWidget->rowCount()-1,3)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    ui->tableWidget->scrollToBottom();
}

void DecoderWidget::on_pushButton_export_clicked()
{
    int rows = ui->tableWidget->rowCount();//表格总行数
    if(rows == 0)
    {
        showHintLabel(this,tr("表格为空，无数据可导出！"));
        return ;
    }
    //获取创建的csv文件名
    QString fileName = QFileDialog::getSaveFileName(this, tr("Excel file"), qApp->applicationDirPath (),
                                              tr("Files (*.csv)"));
    if (fileName.isEmpty()) return;

    QFile file(fileName);
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))//打开.csv文件
    {
        QMessageBox::information(this, tr("错误"), tr("文件导出失败！").arg(fileName), tr("确定"));
        return;
    }
    QTextStream out(&file);

    out << tr("计数,") << tr("左通道,")<< tr("右通道,") << tr("对比结果,") <<",\n";    //添加表头
    //获取表格内容
    for(int i = 0; i < rows; i ++)
    {
      for(int col = 0; col < 4; col++)
      {
          QString string = ui->tableWidget->item(i, col)->text();
          out << string << ",";// 写入文件
      }
      out << "\n";
    }
    QMessageBox::information(this, tr("导出数据成功"), tr("信息已保存在:\n %1！").arg(fileName), tr("确定"));
    file.close();
}

QImage DecoderWidget::AdjustContrast(QImage Img, int iContrastValue)
{
    int pixels = Img.width() * Img.height();
    unsigned int *data = (unsigned int *)Img.bits();

    int red, green, blue, nRed, nGreen, nBlue;

    if (iContrastValue > 0 && iContrastValue < 100)
    {
        float param = 1 / (1 - iContrastValue / 100.0) - 1;

        for (int i = 0; i < pixels; ++i)
        {
            nRed = qRed(data[i]);
            nGreen = qGreen(data[i]);
            nBlue = qBlue(data[i]);

            red = nRed + (nRed - 127) * param;
            red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
            green = nGreen + (nGreen - 127) * param;
            green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
            blue = nBlue + (nBlue - 127) * param;
            blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;

            data[i] = qRgba(red, green, blue, qAlpha(data[i]));
        }
    }
    else
    {
        for (int i = 0; i < pixels; ++i)
        {
            nRed = qRed(data[i]);
            nGreen = qGreen(data[i]);
            nBlue = qBlue(data[i]);

            red = nRed + (nRed - 127) * iContrastValue / 100.0;
            red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
            green = nGreen + (nGreen - 127) * iContrastValue / 100.0;
            green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
            blue = nBlue + (nBlue - 127) * iContrastValue / 100.0;
            blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;

            data[i] = qRgba(red, green, blue, qAlpha(data[i]));
        }
    }

    return Img;
}



